package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.apis.article.ArticleClient;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.exception.CustomException;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ContentDto;
import com.heima.model.common.dtos.ContentImagesDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoAuditService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author:篍
 * @Date: 2025/09/24 17:10
 * @Description:
 */
@Service
@Slf4j
public class WmNewsAutoAuditServiceImpl implements WmNewsAutoAuditService {

    @Autowired
    private ArticleClient articleClient;
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    private Tess4jClient tess4jClient;
    @Autowired
    private RedissonClient redissonClient;


    /**
     * 自管理的敏感词过滤
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitiveScan(String content, WmNews wmNews) {

        boolean flag = true;

        //获取所有的敏感词
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
        List<String> sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看文章中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if(!map.isEmpty()){
            wmNews.setStatus(WmNews.Status.FAIL.getCode());
            wmNews.setReason("当前文章或者图片文字中存在违规内容"+map);
            wmNewsMapper.updateById(wmNews);
            flag = false;
        }
        return flag;
    }

    /**
     * 审核图片
     *
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleImageScan(List<String> images, WmNews wmNews) {

        boolean flag = true;

        if (images == null || images.size() == 0) {
            return flag;
        }

        //下载图片 minIO
        //图片去重
        images = images.stream().distinct().collect(Collectors.toList());

        List<byte[]> imageList = new ArrayList<>();

        try {
            for (String image : images) {
                byte[] bytes = fileStorageService.downLoadFile(image);

                //图片识别文字审核---begin-----

                //从byte[]转换为butteredImage
                ByteArrayInputStream in = new ByteArrayInputStream(bytes);
                BufferedImage imageFile = ImageIO.read(in);
                //识别图片的文字
                String result = tess4jClient.doOCR(imageFile);

                //审核是否包含自管理的敏感词
                boolean isSensitive = handleSensitiveScan(result, wmNews);
                if(!isSensitive){
                    return isSensitive;
                }

                //图片识别文字审核---end-----


                imageList.add(bytes);

            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 自动审核文章
     * @param wmNewsId
     */
    @Override
    @Async
    public void autoAudit(Integer wmNewsId) {
        WmNews wmNews = wmNewsMapper.selectById(wmNewsId);
        if (Objects.isNull(wmNews)){
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (wmNews.getStatus().equals(WmNews.Status.NORMAL.getCode())){
            return;
        }
        //自管理的敏感词过滤
        Map<String, Object> textAndImages = handleTextAndImages(wmNews);
        boolean isSensitive = handleSensitiveScan((String) textAndImages.get("content"), wmNews);
        if (!isSensitive){
            return;
        }
        //图片中的文字审核
        boolean textInImageIsSensitive = handleImageScan((List<String>) textAndImages.get("images"), wmNews);
        if (!textInImageIsSensitive){
            return;
        }
        if (wmNews.getPublishTime().after(new Date())){
            //未到达发布时间
            wmNews.setStatus(WmNews.Status.SUCCESS.getCode());
            wmNews.setReason("审核通过");
            wmNewsMapper.updateById(wmNews);
            //延时发布文章
            RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque("article-deque");
            RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
            long delayTime= wmNews.getPublishTime().getTime()-System.currentTimeMillis();
            //向延时队列中添加任务
            delayedQueue.offer(wmNewsId,delayTime, TimeUnit.MILLISECONDS);
        }else {
            //到达发布时间,发布文章
            publishArticle(wmNewsId);
        }
    }

    @Override
    public void publishArticle(Integer wmNewsId) {
        WmNews wmNews = wmNewsMapper.selectById(wmNewsId);
        //到达发布时间,发布文章
        ArticleDto articleDto = new ArticleDto();
        articleDto.setContent(wmNews.getContent());
        articleDto.setTitle(wmNews.getTitle());
        articleDto.setAuthorId(Long.valueOf(wmNews.getUserId()));
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (Objects.isNull(wmUser)){
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        articleDto.setAuthorName(wmUser.getName());
        articleDto.setChannelId(wmNews.getChannelId());
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (Objects.isNull(wmChannel)){
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        articleDto.setChannelName(wmChannel.getName());
        articleDto.setLayout(wmNews.getType());
        articleDto.setFlag((byte)0);
        articleDto.setImages(wmNews.getImages());
        articleDto.setLabels(wmNews.getLabels());
        articleDto.setCreatedTime(wmNews.getCreatedTime());
        articleDto.setPublishTime(wmNews.getPublishTime());
        saveApArticle(wmNews,articleDto);
    }

    /**
     * 1。从自媒体文章的内容中提取文本和图片
     * 2.提取文章的封面图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {

        //存储纯文本内容
        StringBuilder stringBuilder = new StringBuilder();

        List<String> images = new ArrayList<>();

        //1。从自媒体文章的内容中提取文本和图片
        if (StringUtils.isNotBlank(wmNews.getContent())) {
            List<Map> maps = JSONArray.parseArray(wmNews.getContent(), Map.class);
            for (Map map : maps) {
                if (map.get("type").equals("text")) {
                    stringBuilder.append(map.get("value"));
                }

                if (map.get("type").equals("image")) {
                    images.add((String) map.get("value"));
                }
            }
        }
        //2.提取文章的封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("content", stringBuilder.toString());
        resultMap.put("images", images);
        return resultMap;

    }

    /**
     * 保存app端文章,更新wmNews
     * @param articleDto
     */
    //TODO 全局事务注解
    private void saveApArticle(WmNews wmNews,ArticleDto articleDto) {
        wmNews.setReason("审核通过");
        wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
        ResponseResult responseResult = articleClient.saveApArticle(articleDto);
        Long articleId = (Long) responseResult.getData();
        if (articleId>0){
            wmNews.setArticleId(articleId);
            wmNewsMapper.updateById(wmNews);
        }else {
            //降级
            log.error("保存文章失败");
            throw new CustomException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }
}
